package com.demo.springmvc底层演示.demo3;

import java.util.ArrayList;
import java.util.List;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.method.annotation.ExpressionValueMethodArgumentResolver;
import org.springframework.web.method.annotation.RequestHeaderMethodArgumentResolver;
import org.springframework.web.method.annotation.RequestParamMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodArgumentResolverComposite;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.mvc.method.annotation.PathVariableMethodArgumentResolver;
import org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor;
import org.springframework.web.servlet.mvc.method.annotation.ServletCookieValueMethodArgumentResolver;
import org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod;
import org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor;
import org.springframework.web.servlet.mvc.method.annotation.ServletRequestDataBinderFactory;
import org.springframework.web.servlet.mvc.method.annotation.ServletRequestMethodArgumentResolver;

//request参数处理 + 绑定
public class Test {
	
	public static void main(String[] args) throws Exception {
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(WebConfig.class);
		MockHttpServletRequest request = new MockHttpServletRequest();
		MockHttpServletResponse response = new MockHttpServletResponse();
		request.setParameter("name", "张三");
		
		// 现在可以通过ServletInvocableHandlerMethod把这些整合在一起，并完成控制器方法的调用
		ServletInvocableHandlerMethod handlerMethod = new ServletInvocableHandlerMethod(new WebConfig.Controller1(), WebConfig.Controller1.class.getMethod("foo", WebConfig.User.class));
		ServletRequestDataBinderFactory factory = new ServletRequestDataBinderFactory(null, null);
		handlerMethod.setDataBinderFactory(factory);
		handlerMethod.setParameterNameDiscoverer(new DefaultParameterNameDiscoverer());
		HandlerMethodArgumentResolverComposite composite = new HandlerMethodArgumentResolverComposite();
		List<HttpMessageConverter<?>> converters = new ArrayList<HttpMessageConverter<?>>() {{
			add(new MappingJackson2HttpMessageConverter());
		}};
		composite.addResolvers(
			// false: 表示必须有@RequestParam注解的参数才会被解析；true: 不写也会尝试解析
			new RequestParamMethodArgumentResolver(context.getBeanFactory(), false),
			new PathVariableMethodArgumentResolver(),
			new RequestHeaderMethodArgumentResolver(context.getBeanFactory()),
			new ServletCookieValueMethodArgumentResolver(context.getBeanFactory()),
			new ExpressionValueMethodArgumentResolver(context.getBeanFactory()),
			new ServletRequestMethodArgumentResolver(),
			new ServletModelAttributeMethodProcessor(false),
			new RequestResponseBodyMethodProcessor(converters),
			new ServletModelAttributeMethodProcessor(true),
			new RequestParamMethodArgumentResolver(context.getBeanFactory(), true)
		);
		handlerMethod.setHandlerMethodArgumentResolvers(composite);
		
		ModelAndViewContainer mavContainer = new ModelAndViewContainer();
		handlerMethod.invokeAndHandle(new ServletWebRequest(request, response), mavContainer, null);
	}

}
